package com.teamwings.config.druid;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.teamwings.config.druid.vo.DataSourceVO;
import com.teamwings.util.DBUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableTransactionManagement
public class DruidDBConfig {

	private final Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);

	@Value("${spring.datasource.druid.unitId}")
	private String unitId;
	@Value("${spring.datasource.druid.url}")
	private String url;
	@Value("${spring.datasource.druid.username}")
	private String username;
	@Value("${spring.datasource.druid.password}")
	private String password;

	public static String type;

	@Value("${spring.datasource.druid.type}")
	public void type(String type) {
		DruidDBConfig.type = type;
	}

	@Bean
	@Primary
	@Qualifier("mainDataSource")
	public DataSource dataSource() throws SQLException {
		DataSourceVO unitDataBase = DBUtil.getUnitDataBase(unitId, url, username, password);
		DruidDataSource datasource = new DruidDataSource();

		// 基础连接信息
		datasource.setUrl(unitDataBase.getUrl());
		datasource.setUsername(unitDataBase.getUsername());
		datasource.setPassword(unitDataBase.getPassword());
		datasource.setDriverClassName(DBUtil.getDriverClass(unitDataBase.getDbType()));
		// 连接池连接信息
		datasource.setInitialSize(1);
		datasource.setMinIdle(5);
		datasource.setMaxActive(20);
		datasource.setMaxWait(60000);
//		datasource.setPoolPreparedStatements(true); //是否缓存preparedStatement，也就是PSCache。PSCache对支持游标的数据库性能提升巨大，比如说oracle。在mysql下建议关闭。
//		datasource.setMaxPoolPreparedStatementPerConnectionSize(20);
//		//  datasource.setConnectionProperties("oracle.net.CONNECT_TIMEOUT=6000;oracle.jdbc.ReadTimeout=60000");//对于耗时长的查询sql，会受限于ReadTimeout的控制，单位毫秒
//		datasource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");//对于耗时长的查询sql，会受限于ReadTimeout的控制，单位毫秒
		datasource.setTestOnBorrow(true); //申请连接时执行validationQuery检测连接是否有效，这里建议配置为TRUE，防止取到的连接不可用
		datasource.setTestWhileIdle(true);//建议配置为true，不影响性能，并且保证安全性。申请连接的时候检测，如果空闲时间大于timeBetweenEvictionRunsMillis，执行validationQuery检测连接是否有效。
		String validationQuery = "select 1";
		datasource.setValidationQuery(validationQuery); //用来检测连接是否有效的sql，要求是一个查询语句。如果validationQuery为null，testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
//		datasource.setFilters("stat,wall");//属性类型是字符串，通过别名的方式配置扩展插件，常用的插件有：监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
//		datasource.setTimeBetweenEvictionRunsMillis(60000); //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
//		datasource.setMinEvictableIdleTimeMillis(180000); //配置一个连接在池中最小生存的时间，单位是毫秒，这里配置为3分钟180000
//		datasource.setKeepAlive(true); //打开druid.keepAlive之后，当连接池空闲时，池中的minIdle数量以内的连接，空闲时间超过minEvictableIdleTimeMillis，则会执行keepAlive操作，即执行druid.validationQuery指定的查询SQL，一般为select * from dual，只要minEvictableIdleTimeMillis设置的小于防火墙切断连接时间，就可以保证当连接空闲时自动做保活检测，不会被防火墙切断
//		datasource.setRemoveAbandoned(true); //是否移除泄露的连接/超过时间限制是否回收。
//		datasource.setRemoveAbandonedTimeout(3600); //泄露连接的定义时间(要超过最大事务的处理时间)；单位为秒。这里配置为1小时
//		datasource.setLogAbandoned(true); // 移除泄露连接发生是是否记录日志
		DBUtil.initTenantTables(datasource);
		logger.info("配置单位库数据源成功");
		return datasource;
	}

	/**
	 * druid监控页面配置：账号密码配置
	 * @return ServletRegistrationBean
	 */
	@Bean
	public ServletRegistrationBean druidStatViewServlet() {
		ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
				new StatViewServlet(), "/druid/*");
		servletRegistrationBean.addInitParameter("loginUsername", "admin");
		servletRegistrationBean.addInitParameter("loginPassword", "123456");
		servletRegistrationBean.addInitParameter("resetEnable", "false");
		return servletRegistrationBean;
	}

	/**
	 * druid监控页面配置：允许页面正常浏览
	 * @return FilterRegistrationBean
	 */
	@Bean
	public FilterRegistrationBean druidStatFilter() {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(
				new WebStatFilter());
		// 添加过滤规则.
		filterRegistrationBean.addUrlPatterns("/*");
		// 添加不需要忽略的格式信息.
		filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
		return filterRegistrationBean;
	}

	@Bean(name = "dynamicDataSource")
	@Qualifier("dynamicDataSource")
	public DynamicDataSource dynamicDataSource() throws SQLException {
		DynamicDataSource dynamicDataSource = new DynamicDataSource();
		DataSource dataSource = dataSource();
		dynamicDataSource.setDebug(false);
		//配置缺省的数据源
		dynamicDataSource.setDefaultTargetDataSource(dataSource);
		Map<Object, Object> targetDataSources = new HashMap<Object, Object>();

		targetDataSources.put(unitId, dataSource);
		dynamicDataSource.setTargetDataSources(targetDataSources);
		return dynamicDataSource;
	}

//	@Bean
//	public SqlSessionFactory sqlSessionFactory() throws Exception {
//		MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean ();
//		sqlSessionFactoryBean.setDataSource(dynamicDataSource());
//		//解决手动创建数据源后字段到bean属性名驼峰命名转换失效的问题
//		sqlSessionFactoryBean.setConfiguration(configuration());

		// 设置mybatis的主配置文件
//		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		// Resource mybatisConfigXml = resolver.getResource("classpath:mybatis/mybatis-config.xml");
		//  sqlSessionFactoryBean.setConfigLocation(mybatisConfigXml);
		// 设置别名包
		//  sqlSessionFactoryBean.setTypeAliasesPackage("com.testdb.dbsource.pojo");

		//手动配置mybatis的mapper.xml资源路径,如果单纯使用注解方式,不需要配置该行
		// sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mybatis/mapper/*.xml"));
//		return sqlSessionFactoryBean.getObject();
//	}

//	@Bean
//	@ConfigurationProperties(prefix = "mybatis-plus.configuration")
//	public MybatisConfiguration configuration() {
//		return new MybatisConfiguration();
//	}
}
